#include "stdafx.h"
#include "CXString.h"
#include "IPALCoreServices.h"
#include "CCharTypes.h"

extern IPALCoreServices * GetPALCoreServices();


XSTRING_BASE s_xstrEmptyString = 
{
	0,
	L"",
	1
};

XSTRING_BASE s_xstrNullString = {0,0,2};

void TrimWhitespace(UINT32 *pcString, const XCHAR * *ppString)
{
	while ( *pcString && xisspace(**ppString) )
	{
		++*ppString;
		--*pcString;
	}

}

void TrimTrailingWhitespace(UINT32 *pcString, const XCHAR * *ppString)
{
	while ( *pcString && xisspace((*ppString)[*pcString - 1]) )
		--*pcString;
}






CXString::CXString()
{
	NOTIMPL
}

CXString::CXString( const struct XSTRING_BASE & rXSTRING )
{
	this->pString = rXSTRING.pString;
	this->cString = rXSTRING.cString;
	this->flags = 0;
}

CXString::CXString( XUINT32 cchString, XCHAR * pchString )
{
	if ( this->MaskOffOwnerFlag(pchString) != pchString )
	{
		//error
	}
	this->flags = 0;
	if ( this->MaskOffOwnerFlag(pchString) == pchString )
	{
		this->pString = pchString;
		this->cString = cchString;
	}
	else
	{
		this->cString = 0;
		this->pString = NULL;
	}
}

void CXString::operator delete( void * ptr )
{
	NOTIMPL
}

CXString::~CXString()
{
	NOTIMPL
}

CXString * CXString::Create( XUINT32 cch, XBOOL bPublic )
{
	CXString *result;

	CXString *pNew = NULL;
	if ( cch <= 0x7FFFFFF5 )
	{
		if ( bPublic )
		{
			void *pchBuffer = new char[2 * (cch + 1)];
			if ( pchBuffer )
			{
				*(WCHAR *)pchBuffer = NULL;
				pNew = CXString::WrapBuffer((XCHAR * )pchBuffer, 0, cch, TRUE);
				if ( !pNew )
					delete[] pchBuffer;
			}
		}
		else
		{
			pNew = (CXString *)new char[2 * (cch + 10)];
			if ( pNew )
				pNew->InitializeBuffer(cch);
		}
		result = pNew;
	}
	else
	{
		result = NULL;
	}
	return result;
}

HRESULT CXString::CreateFromUInt32( XUINT32 value, CXString * * ppstrValue )
{
	HRESULT hr = S_OK;
	unsigned int cBuffer = 0;
	CXString *pstrValue = NULL;
	XCHAR * pBuffer = xstritoa(value, &cBuffer);
	if ( pBuffer )
	{
		pstrValue = CXString::WrapBuffer(pBuffer, cBuffer, cBuffer, TRUE);
		if ( pstrValue )
		{
			pBuffer = NULL;
			*ppstrValue = pstrValue;
			pstrValue = NULL;
		}
		else
		{
			hr = 0x8007000Eu;
		}
	}
	else
	{
		hr = 0x8007000Eu;
	}

	delete[] pBuffer;
	if ( pstrValue )
		delete pstrValue;
	return hr;
}

HRESULT CXString::CreateFromInt32( XINT32 value, CXString * * ppstrValue )
{
	NOTIMPL
}

CXString * CXString::WrapBuffer( XCHAR * pchSource, XUINT32 cchValid, XUINT32 cchBufferLength, XBOOL bTakeOwnership )
{
	void *pNew = new char[sizeof(CXString)];
	if ( pNew )
		((CXString *)pNew)->InitializeWrappedBuffer(pchSource, cchValid, cchBufferLength, bTakeOwnership);
	return (CXString *)pNew;
}

CXString * CXString::WrapBuffer( XUINT32 cchValid, XCHAR * pchSource )
{
	return CXString::WrapBuffer(pchSource, cchValid, cchValid, FALSE);
}

CXString * CXString::Clone( XBOOL bConnectedBuffer, XBOOL bTrimBuffer ) const
{
	unsigned int cch; 
	CXString *pTemp; 

	if ( bTrimBuffer )
		cch = this->GetCount();
	else
		cch = this->BufferLength();
	pTemp = CXString::Create(cch, bConnectedBuffer == 0);
	if ( pTemp )
		pTemp->Append(this);
	return pTemp;
}

CXString * CXString::CloneBuffer( const XCHAR * pchSource, XUINT32 cchValid )
{
	return CXString::CloneBuffer(pchSource, cchValid, cchValid, FALSE);
}

CXString * CXString::CloneBuffer( const XCHAR * pchSource, XUINT32 cchValid, XUINT32 cchBufferLength, XINT32 bPublic )
{
	CXString *pstrReturn;

	pstrReturn = CXString::Create(cchBufferLength, bPublic);
	if ( pstrReturn && pstrReturn->Append(pchSource, cchValid) < 0 )
	{
		if ( pstrReturn )

			delete pstrReturn;
		pstrReturn = NULL;
	}
	return pstrReturn;
}

CXString * CXString::CloneBufferTrimWhitespace( XCHAR * pchSource, XUINT32 cchValid )
{
	const XCHAR * pchString;
	unsigned int cchString;

	cchString = cchValid;
	pchString = pchSource;
	TrimWhitespace(&cchString,&pchString);
	TrimTrailingWhitespace(&cchString, &pchString);
	return CXString::CloneBuffer(pchString, cchString, cchString, FALSE);
}

CXString * CXString::Concatenate( const CXString & pstrFront, XUINT32 ichFrontStart, const CXString & pstrBack, XUINT32 ichBackStart )
{

	CXString *pstrReturn = NULL;


	if ( ichFrontStart > const_cast<CXString &>(pstrFront).GetCount() || ichBackStart > const_cast<CXString &>(pstrBack).GetCount() )
	{

		//error
	}
	unsigned int frontCount = const_cast<CXString &>(pstrFront).GetCount() - ichFrontStart;
	unsigned int backCount = const_cast<CXString &>(pstrBack).GetCount() - ichBackStart;
	if ( frontCount > -1 - backCount )
	{
		//error
	}
	pstrReturn = CXString::Create(backCount + frontCount, FALSE);
	if ( pstrReturn )
	{
		if ( pstrReturn->AppendPrivate(pstrFront, 0, ichFrontStart, frontCount) < 0 || (pstrReturn->AppendPrivate(pstrBack, pstrReturn->GetCount(), ichBackStart, backCount) < 0) )
		{
			if ( pstrReturn )
				delete pstrReturn;
			pstrReturn = NULL;
		}
	}
	return pstrReturn;
}

CXString * CXString::Concatenate( const CXString * pstrFront, XUINT32 ichFrontStart, const CXString * pstrBack, XUINT32 ichBackStart )
{
	 return CXString::Concatenate((CXString const &)pstrFront, ichFrontStart, (CXString const &)pstrBack, ichBackStart);
}

CXString * CXString::EmptyString()
{
	return (CXString *)&s_xstrEmptyString;
}

CXString * CXString::NullString()
{
	return (CXString *)&s_xstrNullString;
}

CXString * CXString::SubString( const XUINT32 startIndex, const XUINT32 endIndex ) const
{
	CXString *result;
	if ( startIndex <= this->GetCount() && endIndex <= this->GetCount() && startIndex <= endIndex )
	{
		result = CXString::CloneBuffer(&this->GetBuffer()[startIndex], endIndex - startIndex, endIndex - startIndex, FALSE);
	}
	else
	{
		result = NULL;
	}
	return result;
}

HRESULT CXString::Insert( const XCHAR * pchSource, XUINT32, XUINT32 )
{
	NOTIMPL
}

HRESULT CXString::Insert( const CXString * pstrSource, XUINT32, XUINT32, XUINT32 )
{
	NOTIMPL
}

HRESULT CXString::Insert( const CXString * pstrSource, XUINT32, XUINT32 )
{
	NOTIMPL
}

HRESULT CXString::Insert( const CXString * pstrSource, XUINT32 )
{
	NOTIMPL
}

HRESULT CXString::Remove( XUINT32 ichStart, XUINT32 cchRemove )
{
	XCHAR * pBuffer; 
	HRESULT hr = S_OK;

	pBuffer = this->GetBuffer();
	if ( cchRemove + ichStart <= this->GetCount() )
	{
		memmove((void *)&pBuffer[ichStart], &pBuffer[cchRemove + ichStart], 2 * (this->GetCount() - (cchRemove + ichStart)));
		this->cString -= cchRemove;
		pBuffer[this->cString] = NULL;
	}
	else
	{
		hr = E_FAIL;
	}
	return hr;
}

HRESULT CXString::Append( const XCHAR * pchSource, XUINT32 cchAppend )
{
	HRESULT hr = 0x80070057u;
	if ( pchSource )
		hr = this->AppendPrivate(pchSource, cchAppend, this->GetCount());
	return hr;
}

HRESULT CXString::Append( const CXString * pstrSource, XUINT32, XUINT32, XUINT32 )
{
	NOTIMPL
}

HRESULT CXString::Append( const CXString * pstrSource, XUINT32, XUINT32 )
{
	NOTIMPL
}

HRESULT CXString::Append( const CXString * pstrSource, XUINT32 ichTargetIndex )
{
	HRESULT hr = 0x80070057u;
	if ( pstrSource )
		hr = this->AppendPrivate(pstrSource, ichTargetIndex, 0, const_cast<CXString *>(pstrSource)->GetCount());
	return hr;
}

HRESULT CXString::Append( const CXString * pstrSource )
{
	HRESULT hr = 0x80070057u;
	if ( pstrSource )
		hr = this->Append(pstrSource);
	return hr;
}

HRESULT CXString::Append( const CXString & rSource )
{
	return this->AppendPrivate(rSource, this->GetCount(), 0,const_cast<CXString &>(rSource).GetCount());
}

HRESULT CXString::AppendChar( XCHAR chSource )
{
	HRESULT hr = E_FAIL;
	if ( this->BufferLengthRemaining() )
	{
		this->GetBuffer()[this->cString++] = chSource;
		this->GetBuffer()[this->cString] = NULL;
		hr = S_OK;
	}
	return hr;
}

HRESULT CXString::Find( const CXString * pstrSource, XUINT32 ichStartingIndex, enum xstrCompareBehavior eCompareBehavior, XUINT32 * pichFound ) const
{
	int result;
	unsigned int v6; 

	WCHAR * pchBuffer; 

	XCHAR * pchFound; 

	HRESULT hr = 0x80004005u;

	if ( ichStartingIndex < -1 - const_cast<CXString *>(pstrSource)->GetCount() )
	{
		v6 = ichStartingIndex + const_cast<CXString *>(pstrSource)->GetCount();
		if ( v6 <= this->GetCount() )
		{
			pchBuffer = &this->GetBuffer()[ichStartingIndex];
			if ( eCompareBehavior )
			{
				pchFound = xstrnistr(pchBuffer, const_cast<CXString *>(pstrSource)->GetBuffer(), const_cast<CXString *>(pstrSource)->GetCount());
			}
			else
			{
				pchFound = xstrnstr(pchBuffer, const_cast<CXString *>(pstrSource)->GetBuffer(), const_cast<CXString *>(pstrSource)->GetCount());
			}
			if ( pchFound )
			{
				*pichFound = pchFound - this->GetBuffer();
				hr = S_OK;
			}
		}
		result = hr;
	}
	else
	{
		result = 0x80004005u;
	}
	return result;
}

HRESULT CXString::Find( const CXString * pstrSource, enum xstrCompareBehavior eCompareBehavior, XUINT32 * pichFound ) const
{
	return this->Find(pstrSource, 0, eCompareBehavior, pichFound);
}

HRESULT CXString::Find( const CXString * pstrSource, enum xstrCompareBehavior eCompareBehavior, XUINT32 * pichFound )
{
	return this->Find(pstrSource, 0, eCompareBehavior, pichFound);
}

HRESULT CXString::Find( const CXString * pstrSource, XUINT32 * pichFound )
{
	NOTIMPL
}

HRESULT CXString::FindChar( const XCHAR ch, XUINT32 * pichFound ) const
{
	return this->FindChar(ch, 0, pichFound);
}

HRESULT CXString::FindChar( const XCHAR ch, XUINT32 ichStartingIndex, XUINT32 * pichFound ) const
{
	unsigned int v8;
	int v9;

	unsigned int ichFound;
	XCHAR * pchBuffer; 
	unsigned int pchBuffera; 
	unsigned int cch; 
	unsigned int ccha; 

	HRESULT hr = E_FAIL;
	pchBuffer = this->GetBuffer();
	cch = this->GetCount();
	if ( pichFound )
	{
		if ( ichStartingIndex < this->GetCount() )
		{
			ccha = cch - ichStartingIndex;
			pchBuffera = (unsigned int)&pchBuffer[ichStartingIndex];
			for ( ichFound = ichStartingIndex; ; ++ichFound )
			{
				v8 = ccha--;
				if ( !v8 )
					break;
				v9 = *(WCHAR *)pchBuffera;
				pchBuffera += 2;
				if ( v9 == ch )
				{
					*pichFound = ichFound;
					return S_OK;
				}
			}
		}
		else
		{
			hr = E_FAIL;
		}
	}
	else
	{
		hr = 0x80004003u;
	}
	return hr;
}

HRESULT CXString::FindLastChar( const XCHAR ch, XUINT32 * pichFound )
{
	NOTIMPL
}

HRESULT CXString::FindLastChar( const XCHAR ch, XUINT32 ichStartingIndex, XUINT32 * pichFound ) const
{
	unsigned int v8; 
	int v9; 

	unsigned int cch;
	unsigned int ichFound; 
	XCHAR * pchBuffer; 
	unsigned int pchBuffera; 
	int hr; 

	hr = E_FAIL;
	pchBuffer = this->GetBuffer();
	cch = ichStartingIndex;
	if ( pichFound )
	{
		if ( ichStartingIndex <= this->GetCount() )
		{
			pchBuffera = (unsigned int)&pchBuffer[ichStartingIndex];
			for ( ichFound = ichStartingIndex; ; --ichFound )
			{
				v8 = cch--;
				if ( !v8 )
					break;
				v9 = *(WCHAR *)pchBuffera;
				pchBuffera -= 2;
				if ( v9 == ch )
				{
					*pichFound = ichFound;
					return S_OK;
				}
			}
		}
		else
		{
			hr = E_FAIL;
		}
	}
	else
	{
		hr = 0x80004003u;
	}
	return hr;
}

HRESULT CXString::Replace( const XCHAR oldChar, const XCHAR newChar )
{
	XCHAR * pBuffer;

	unsigned int i;

	pBuffer = this->GetBuffer();
	for ( i = 0; i < this->GetCount(); ++i )
	{
		if ( pBuffer[i] == oldChar )
			pBuffer[i] = newChar;
	}
	return S_OK;
}

XINT32 CXString::StartsWith( const CXString * pstrStringToFind, enum xstrCompareBehavior eCompareBehavior ) const
{
	int result;

	if ( this->GetCount() < const_cast<CXString *>(pstrStringToFind)->GetCount() )
	{
		result = 0;
	}
	else
	{
		result = this->Compare(pstrStringToFind, 0, const_cast<CXString *>(pstrStringToFind)->GetCount(), eCompareBehavior) == 0;
	}
	return result;
}

XINT32 CXString::EndsWith( const CXString & strStringToFind, enum xstrCompareBehavior eCompareBehavior ) const
{
	int result;

	if ( this->GetCount() < const_cast<CXString &>(strStringToFind).GetCount() )
	{
		result = 0;
	}
	else
	{
		result = this->Compare(strStringToFind, 
			this->GetCount() - const_cast<CXString &>(strStringToFind).GetCount(), 
			const_cast<CXString &>(strStringToFind).GetCount(), 
			eCompareBehavior) == 0;
	}
	return result;
}

XINT32 CXString::EndsWith( const CXString * pstrStringToFind, enum xstrCompareBehavior eCompareBehavior ) const
{
	NOTIMPL
}

HRESULT CXString::ReplaceAtEnd( const CXString * pstrOld, const CXString * pstrNew, enum xstrCompareBehavior eCompareBehavior, CXString * * ppStr )
{
	NOTIMPL
}

XBOOL CXString::IsAllWhitespace()
{
	NOTIMPL
}

XBOOL CXString::Equals( const CXString & rstrSource, enum xstrCompareBehavior eCompareBehavior ) const
{
	unsigned int result;


	if ( const_cast<CXString &>(rstrSource).GetCount() == this->GetCount() )
	{
		if ( const_cast<CXString &>(rstrSource).GetBuffer() == this->GetBuffer() )
		{
			result = 1;
		}
		else
		{
			result = this->Compare(rstrSource, 0, this->GetCount(), eCompareBehavior) == 0;
		}
	}
	else
	{
		result = 0;
	}
	return result;
}

XBOOL CXString::Equals( const CXString * pstrSource, enum xstrCompareBehavior eCompareBehavior ) const
{
	unsigned int result;

	if ( pstrSource )
		result = this->Equals((CXString const &)pstrSource, eCompareBehavior);
	else
		result = 0;
	return result;
}

XCHAR CXString::GetChar( XUINT32 ichIndex ) const
{
	WCHAR ret;

	if ( ichIndex >= this->GetCount() )
		ret = NULL;
	else
		ret = this->GetBuffer()[ichIndex];
	return ret;
}

XINT32 CXString::Compare( const CXString & rstrSource, XUINT32 ichStartingIndex, XUINT32 cchCompare, enum xstrCompareBehavior eCompareBehavior ) const
{
	XCHAR * pBuffer = const_cast<CXString &>(rstrSource).GetBuffer();

	HRESULT hr = S_OK;
	unsigned int count;
	unsigned int i = 0;
	if ( this->GetCount() >= cchCompare )
		count = cchCompare;
	else
		count = this->GetCount();
	while ( !hr && i < count )
	{
		hr = this->CompareChar(pBuffer[i], ichStartingIndex + i, eCompareBehavior);
		++i;
	}
	return hr;
}

XINT32 CXString::Compare( const CXString * pstrSource, XUINT32 ichStartingIndex, XUINT32 cchCompare, enum xstrCompareBehavior eCompareBehavior ) const
{
	return this->Compare((CXString const &)pstrSource, ichStartingIndex, cchCompare, eCompareBehavior);
}

XINT32 CXString::Compare( const CXString * pstrSource, XUINT32 ichStartingIndex, enum xstrCompareBehavior eCompareBehavior )
{
	NOTIMPL
}

XINT32 CXString::Compare( const CXString * pstrSource, enum xstrCompareBehavior eCompareBehavior ) const
{
	int result; 


	unsigned int len;
	unsigned int otherLength;
	unsigned int thisLength; 

	HRESULT hr = S_OK;
	unsigned int i = 0;
	if ( pstrSource )
	{
		XCHAR * pBuffer =const_cast<CXString *>(pstrSource)->GetBuffer();
		thisLength = this->GetCount();
		otherLength = const_cast<CXString *>(pstrSource)->GetCount();
		if ( thisLength >= otherLength )
			len = otherLength;
		else
			len = thisLength;
		while ( !hr && i < len )
		{
			hr = this->CompareChar(pBuffer[i], i, eCompareBehavior);
			++i;
		}
		if ( hr )
			result = hr;
		else
			result = thisLength - otherLength;
	}
	else
	{
		result = -1;
	}
	return result;
}

XINT32 CXString::CompareChar( const XCHAR ch, XUINT32 ichStartingIndex, enum xstrCompareBehavior eCompareBehavior ) const
{
	int result;

	if ( ichStartingIndex <= this->GetCount() )
	{
		XCHAR * pstr;
		if ( eCompareBehavior )
		{
			pstr = this->GetBuffer();
			result = xstrncmpi(&ch, &pstr[ichStartingIndex], 1u);
		}
		else
		{
			pstr = this->GetBuffer();
			result = ch - pstr[ichStartingIndex];
		}
	}
	else
	{
		result = ch;
	}
	return result;
}

void CXString::DebugValidate() const
{
	if ( this->pString )
	{
		int pchBuffer = (unsigned int)this->pString & 0xFFFFFFFE;
		unsigned int cchValid = this->cString;

		//auto fff = (!OwnsBuffer() || !pchBuffer || pchBuffer[cchValid] == NULL);
		//TRACE_ENSURE((!OwnsBuffer() || !pchBuffer || pchBuffer[cchValid] == NULL));


		if ( this->OwnsBuffer() )
		{
			if ( pchBuffer )
			{
				if ( *(WCHAR *)(pchBuffer + 2 * cchValid) )
				{
					//v4 = GetPALDebuggingServices();
					//if ( v4->vfptr->XcpTrace(
					//	v4,
					//	1u,
					//	L"windows\\dxaml\\xcp\\pal\\common\\xstring.cpp",
					//	1420,
					//	0,
					//	L"!OwnsBuffer() || !pchBuffer || pchBuffer[cchValid] == NULL",
					//	&sakns_0_1a) )
					//{
					//	if ( IsDebuggerPresent() )
					//	{
					//		DebugBreak();
					//	}
					//	else
					//	{
					//		OnNewFailureEncountered(-2147418113, 0);
					//		GetStowedExceptionsForFailFast(&ppStowedExceptions, (unsigned int *)&cStowedExceptions);
					//		RoFailFastWithErrorContextInternal(-2147418113, cStowedExceptions, ppStowedExceptions);
					//	}
					//}
				}
			}
		}
	}
}

XUINT32 CXString::GetCount() const
{
	this->DebugValidate();
	return this->cString;
}

HRESULT CXString::SetCount( XUINT32 )
{
	NOTIMPL
}

XCHAR * CXString::GetBuffer() const
{
	this->DebugValidate();
	return (XCHAR * )((unsigned int)this->pString & 0xFFFFFFFE);
}

CXString * CXString::GetPtr()
{
	NOTIMPL
}

XCHAR * CXString::RelinquishBuffer()
{
	XCHAR * result;

	if ( this->IsConnectedBuffer() )
	{
		result = NULL;
	}
	else
	{
		this->pString = (XCHAR * )((unsigned int)this->pString & 0xFFFFFFFE);
		result = this->pString;
	}
	return result;
}

XCHAR * CXString::MakeBufferCopy()
{
	void * bufferCopy = new char[2 * (this->GetCount() + 1) | -((unsigned __int64)(this->GetCount() + 1) >> 31 != 0)];
	if ( bufferCopy )
	{
		xstrncpy((XCHAR * )bufferCopy, (const XCHAR * )this->GetBuffer(), this->GetCount());
		*((WCHAR *)bufferCopy + this->GetCount()) = NULL;
	}
	return (XCHAR * )bufferCopy;
}

HRESULT CXString::CopyToBuffer( XCHAR * * ppchTarget, XUINT32 * pcch )
{
	HRESULT hr = S_OK;
	CXString *pstrTemp = this->Clone(FALSE, TRUE);
	if ( pstrTemp )
	{
		*pcch = pstrTemp->GetCount();
		*ppchTarget = pstrTemp->RelinquishBuffer();
	}
	else
	{
		hr = 0x8007000Eu;
	}
	if ( pstrTemp )
		delete pstrTemp;
	return hr;
}

HRESULT CXString::Trim( XUINT32 toLength )
{
	XCHAR * pchBuffer;

	HRESULT hr = S_OK;
	pchBuffer = this->GetBuffer();
	if ( toLength <= this->GetCount() )
	{
		if ( !this->IsStaticEmptyString() )
		{
			this->cString = toLength;
			pchBuffer[toLength] = NULL;
		}
	}
	else
	{
		hr = E_FAIL;
	}
	return hr;
}

XBOOL CXString::NullOrEmpty( const CXString * pstrString )
{
	return !pstrString || !const_cast<CXString *>(pstrString)->GetCount() || !*const_cast<CXString *>(pstrString)->GetBuffer();
}

XUINT32 CXString::BufferLength() const
{
	unsigned int v2;
	if ( this->OwnsBuffer() )
		v2 = this[1].cString;
	else
		v2 = this->cString;
	return v2;
}

CXString * CXString::CharToWideChar( XUINT32 cstr, char * pstr )
{
	CXString *result = NULL;
	unsigned int cstrTmp = NULL;;
	XCHAR * pBuffer = NULL;
	IPlatformUtilities * pUtilities = NULL;
	if (SUCCEEDED(GetPALCoreServices()->GetPlatformUtilities(&pUtilities)) )
	{
		cstrTmp = cstr;
		pBuffer = pUtilities->CharToWideChar(&cstrTmp, pstr);
		result = CXString::CloneBuffer(pBuffer, cstrTmp);
		delete[] pBuffer;
	}
	else
	{
		result = NULL;
	}
	return result;
}

char * CXString::WideCharToChar( XUINT32 * pcstr, char * pstrDest )
{
	char *result;

	IPlatformUtilities *pUtilities = NULL;
	if ( GetPALCoreServices()->GetPlatformUtilities((IPlatformUtilities **)&pUtilities) >= 0 )
	{

		result = pUtilities->WideCharToChar(this->GetCount(),this->GetBuffer(),pcstr,pstrDest);
	}
	else
	{
		result = NULL;
	}
	return result;
}

const XCHAR * CXString::GetConstBuffer() const
{
	throw std::logic_error("The method or operation is not implemented.");
}

void CXString::InitializeBuffer( XUINT32 cchBuffer )
{
	this->cString = 0;
	this->pString = NULL;
	this->pString = this->ApplyOwnerFlag((XCHAR * )&this->pString);
	this->cString = cchBuffer;
	this->flags = 0;
}

void CXString::InitializeWrappedBuffer( XCHAR * pchSource, XUINT32 cchValid, XUINT32 cchBufferLength, XUINT32 bTakeOwnership )
{
	this->cString = cchValid;
	this->pString = pchSource;
	this->flags = 0;
	if ( bTakeOwnership )
		this->pString = this->ApplyOwnerFlag(this->pString);
	this->cString = cchBufferLength;
}

HRESULT CXString::InsertPrivate( const XCHAR *, XUINT32, XUINT32 )
{
	NOTIMPL
}

HRESULT CXString::InsertPrivate( const CXString *, XUINT32, XUINT32, XUINT32 )
{
	NOTIMPL
}

HRESULT CXString::AppendPrivate( const XCHAR * pchSource, XUINT32 cchSource, XUINT32 ichTargetIndex )
{
	HRESULT hr = S_OK;

	if ( 0xFFFFFFFF - cchSource >= ichTargetIndex )
	{
		if ( cchSource + ichTargetIndex <= this->BufferLength() )
		{
			if ( !this->IsStaticEmptyString() )
			{
				XCHAR * dest = this->GetBuffer();
				memcpy((void *)&dest[ichTargetIndex], pchSource, 2 * cchSource);
				dest[cchSource + ichTargetIndex] = NULL;
				this->cString = cchSource + ichTargetIndex;
			}
		}
		else
		{
			hr = E_FAIL;
		}
	}
	else
	{
		hr = E_FAIL;
	}
	return hr;
}

HRESULT CXString::AppendPrivate( const CXString & rSource, XUINT32 ichTargetIndex, XUINT32 ichSourceIndex, XUINT32 cchSource )
{
	HRESULT hr = S_OK;

	if ( 0xFFFFFFFF - cchSource >= ichTargetIndex && 0xFFFFFFFF - cchSource >= ichSourceIndex )
	{
		if ( cchSource + ichTargetIndex <= this->BufferLength() )
		{
			if ( cchSource + ichSourceIndex <= const_cast<CXString &>(rSource).GetCount() )
			{
				if ( !this->IsStaticEmptyString() )
				{
					XCHAR * dest = this->GetBuffer();
					XCHAR * src = const_cast<CXString &>(rSource).GetBuffer();

					memcpy((void *)&dest[ichTargetIndex], &src[ichSourceIndex], 2 * cchSource);

					dest[cchSource + ichTargetIndex] = NULL;

					this->cString = cchSource + ichTargetIndex;
				}
			}
			else
			{
				hr = E_FAIL;
			}
		}
		else
		{
			hr = E_FAIL;
		}
	}
	else
	{
		hr = E_FAIL;
	}
	return hr;
}

HRESULT CXString::AppendPrivate( const CXString * pstrSource, XUINT32 ichTargetIndex, XUINT32 ichSourceIndex, XUINT32 cchSource )
{
	return this->AppendPrivate((CXString const &)pstrSource, ichTargetIndex, ichSourceIndex, cchSource);
}

XBOOL CXString::OwnsBuffer() const
{
	return (XBOOL)this->pString & 1;
}

XBOOL CXString::IsConnectedBuffer()
{
	XCHAR * bufferPtr = this->GetBuffer();
	return this->OwnsBuffer() && (XCHAR * *)bufferPtr == &this->pString;
}

XUINT32 CXString::BufferLengthRemaining()
{
	return this->BufferLength() - this->cString;
}

XBOOL CXString::IsStaticEmptyString()
{
	return (this->flags & 1) != 0;
}

XCHAR * CXString::ApplyOwnerFlag( XCHAR * pch )
{
	return (XCHAR * )((unsigned int)pch | 1);
}

XCHAR * CXString::MaskOffOwnerFlag( XCHAR * pch )
{
	return (XCHAR * )((unsigned int)pch & 0xFFFFFFFE);
}

//void * XSTRING_BASE::operator new(XUINT32 cSize)
//{
//
//	NOTIMPL
//
//}
